#pragma once

//namespace W
//{
//	template<class T>
//	class shared_ptr {
//	public:
//		shared_ptr(T* ptr = nullptr)
//			:_ptr(ptr)
//		{
//			_pcount = new int(1);
//		}
//
//		template<class D>
//		shared_ptr(T* ptr = nullptr, D del = D())
//			:_ptr(ptr)
//			,_del(del)
//		{
//			_pcount = new int(1);
//		}
//
//		~shared_ptr() {
//			release();
//		}
//
//		shared_ptr(shared_ptr<T>& ptr) {
//			_ptr = ptr.get();
//			_pcount = ptr._pcount;
//			(*_pcount)++;
//			_del = ptr._del;
//		}
//
//		template<class U>
//		shared_ptr(shared_ptr<T>& ptr, U del) {
//			_ptr = ptr.get();
//			_pcount = ptr._pcount;
//			(*_pcount)++;
//			_del = del;
//		}
//
//		shared_ptr(shared_ptr<T>&& ptr) {
//			_ptr = ptr.get();
//			_pcount = ptr._pcount;
//			(*_pcount)++;
//			_del = ptr._del;
//			ptr.release();
//		}
//
//		shared_ptr<T>& operator=(shared_ptr<T>& ptr) {
//			if (_ptr != ptr.get()) {
//				release();
//				_ptr = ptr.get();
//				_pcount = ptr._pcount;
//				(*_pcount)++;
//				_del = ptr._del;
//			}
//			return *this;
//		}
//
//		shared_ptr<T>& operator=(shared_ptr<T>&& ptr) {
//			release();
//			_ptr = ptr.get();
//			_pcount = ptr._pcount;
//			(*_pcount)++;
//			_del = ptr._del;
//			ptr.release();
//			return *this;
//		}
//
//
//		T& operator*() {
//			return *_ptr;
//		}
//
//		T* operator->() {
//			return _ptr;
//		}
//
//		T* get() {
//			return _ptr;
//		}
//
//	private:
//		void release() {
//			if (_ptr == nullptr) return;
//			if (--(*_pcount) == 0) {
//				cout << "~shared_ptr" << endl;
//				_del(_ptr);
//				delete _pcount;
//			}
//			_pcount = nullptr;
//			_ptr = nullptr;
//		}
//
//		T* _ptr;
//		int* _pcount = new int(1);
//		function<void(int*)> _del = [](T* ptr) {delete ptr;ptr = nullptr;};
//	};
//
//	template<class T, class D = default_delete<T> >
//	class unique_ptr {
//	public:
//		unique_ptr(T* ptr = nullptr, D del = D())
//			:_ptr(ptr)
//			, _del(del)
//		{
//		}
//
//		~unique_ptr() {
//			cout << "~unique_ptr" << endl;
//			_del(_ptr);
//			_ptr = nullptr;
//		}
//
//		T* release() {
//			T* tmp = _ptr;
//			_ptr = nullptr;
//			return tmp;
//		}
//
//		unique_ptr(const unique_ptr<T, D>& ptr) = delete;
//
//		unique_ptr(unique_ptr<T, D>&& ptr) {
//			_ptr = ptr.release();
//		}
//
//		unique_ptr<T, D>& operator=(const unique_ptr<T, D>& ptr) = delete;
//
//		unique_ptr<T, D>& operator=(unique_ptr<T, D>&& ptr) {
//			_ptr = ptr.release();
//			return *this;
//		}
//
//		unique_ptr<T, D>& operator=(nullptr_t) {
//			_ptr = nullptr;
//			return *this;
//		}
//
//		T& operator[](size_t i) {
//			return *(_ptr + i);
//		}
//
//		D& get_deleter() {
//			return _del;
//		}
//
//		T& operator*() {
//			return *_ptr;
//		}
//
//		T* operator->() {
//			return _ptr;
//		}
//
//		T* get() {
//			return _ptr;
//		}
//
//	private:
//		T* _ptr;
//		D _del;
//	};
//
//	template<class T>
//	class auto_ptr {
//	public:
//		auto_ptr(T* ptr = nullptr)
//			:_ptr(ptr)
//		{ }
//
//		~auto_ptr() {
//			//cout << "~auto_ptr" << endl;
//			delete _ptr;
//			_ptr = nullptr;
//		}
//
//		T* release() {
//			T* tmp = _ptr;
//			_ptr = nullptr;
//			return tmp;
//		}
//
//		auto_ptr(auto_ptr<T>& ptr) {
//			_ptr = ptr.release();
//		}
//
//		auto_ptr<T>& operator=(auto_ptr<T>& ptr) {
//			if (ptr._ptr != _ptr) {
//				delete _ptr;
//				_ptr = ptr.release();
//			}
//			return *this;
//		}
//
//		auto_ptr<T>& operator=(auto_ptr<T>&& ptr) {
//			delete _ptr;
//			_ptr = ptr.release();
//			return *this;
//		}
//
//
//		T& operator*() {
//			return *_ptr;
//		}
//
//		T* operator->() {
//			return _ptr;
//		}
//
//		T* get() {
//			return _ptr;
//		}
//
//	private:
//		T* _ptr;
//	};
//}